package com.monitor.handler;

import com.monitor.common.response.CodeMsg;
import com.monitor.common.response.ResponseFactory;
import com.monitor.common.response.Result;
import com.monitor.common.response.exp.ResponseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.ArrayList;
import java.util.List;

/**
 * 全局异常拦截
 * @author zhixingbai@creditease.cn
 */
@RestControllerAdvice()
public class ExceptionHandlerBean {

    protected final Logger LOGGER = LoggerFactory.getLogger(this.getClass());

    /**
     * @Description:  @Validated 验证注解全局返回处理
     * @author zhangyutong@niu.com
     * @Date 17/3/29 19:44
     * 如类注解是 @ControllerAdvice 返回json需要添加 @ResponseBody注解,使用 @RestControllerAdvice注解则可以省略
     * 如继承 ResponseEntityExceptionHandler 类 则返回类型不能是Result ,使用spring rest 默认返回类型ResponseEntity
     * @return
     */
    @ExceptionHandler(value = {Exception.class})
    public Result validExceptionHandler(Exception e) {
        String message;
        int code = CodeMsg.INVALID_PARAM;
        if (e instanceof BindException){
            BindException bindingException = (BindException) e;
            message = this.processResponse(bindingException.getBindingResult());
        } else if(e instanceof MethodArgumentNotValidException){
            MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException) e;
            message = this.processResponse(methodArgumentNotValidException.getBindingResult());
        } else if (e instanceof ResponseException){
            ResponseException responseException = (ResponseException) e;
            code = responseException.getCode();
            message = responseException.getMessage();
        } else if( e instanceof HttpMessageNotReadableException) {
//            HttpMessageNotReadableException messageNotReadableException = (HttpMessageNotReadableException) e;
            code = CodeMsg.INVALID_PARAM;
            message = "提交的报文信息读取失败,请检查请求方式和报文是否正确";
        } else{
            code = CodeMsg.ERROR;
            message = e.getMessage();
            LOGGER.warn("ExceptionHandlerBean-无法匹配捕获的异常信息,{}", e.getMessage() , e);
        }
        return ResponseFactory.buildMessage(code, message);
    }

    /**
     * 处理 错误响应
     * @param bindingResult 入参绑定的错误信息
     * @return
     */
    private String processResponse(BindingResult bindingResult) {

        List<ObjectError> errorList = bindingResult.getAllErrors();
        List<String> errMsgList = new ArrayList<>();
        for(ObjectError error : errorList) {
            errMsgList.add(error.getDefaultMessage());
        }
        LOGGER.info("请求参数:{}", bindingResult.getTarget().toString());
        LOGGER.info("请求失败原因:{}", errMsgList.toString());
        return errMsgList.toString();
    }


}
